/* 
    发布订阅模式
    例如: 售楼部购买房子, 目前没有房源, 需要回家等待售楼部的通知
    三步分析: 
        1. 主体(售楼部)
        2. 缓存列表(需要通知的客户的集合)
        3. 事件触发, 执行回调函数(有房源了, 依次通知所需要的客户)
*/

class Event {
  constructor() {
    this.handlers = {};
  }
  listen(eventType, handler) {
    if (!this.handlers[eventType]) {
      this.handlers[eventType] = [];
    }
    this.handlers[eventType].push(handler);
  }
  trigger(eventType, ...arg) {
    const handlers = this.handlers[eventType];
    for (let handler of handlers) {
      handler.apply(this, arg);
    }
  }
  remove(eventType, handler) {
    const currentHandlers = this.handlers[eventType];
    if (currentHandlers) {
      let len = currentHandlers.length;
      for (let i = len - 1; i >= 0; i--) {
        if (currentHandlers[i] === handler) {
          currentHandlers.splice(i, 1);
        }
      }
    }
  }
}
let myEvent = new Event();

const handlerFunc = (...params) => {
  console.log("处理点击事件, 执行的回调函数; 参数: ", params.join("---"));
};

const handlerFunc1 = (...params) => {
  console.log(
    "处理点击事件, 执行的回调函数111111;  参数: ",
    params.join("---")
  );
};

myEvent.listen("click", handlerFunc);
myEvent.listen("click", handlerFunc1);

myEvent.remove("click", handlerFunc1);

myEvent.trigger("click", "lala", "haha");

/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/
/* 使用生活例子 */
{
  // 售楼部
  let salesOffices = {
    clientList: {}, // 客户列表;  {'我要88平': [客户1, 客户2], '我要100平': [客户3, 客户4]}
    listen(key, fn) {
      // key 用来归类的(我要88平), 通知对应的用户, 而不是通知所有用户; (事件类型EventType)
      // fn 通知到位了, 后续的操作; (handlers处理函数)
      // 调用此函数, 将需要的客户存放在客户集合中
      if (!this.clientList[key]) {
        this.clientList[key] = [];
      }
      this.clientList[key].push(fn);
    },
    trigger(...arg) {
      // 触发事件, 通知对应的客户有哪些信息 (参数: key, info1, info2, info3,...)
      const key = arg[0]; // key
      const fns = this.clientList[key];
      for (let fn of fns) {
        fn.apply(this, arg.slice(1));
      }
    },
    remove(key, fn) {
      // key (事件类型EventType)
      const currenFns = this.clientList[key];
      if (currenFns) {
        let len = currenFns.length;
        for (let i = len - 1; i >= 0; i--) {
          if (currenFns[i] === fn) {
            currenFns.splice(i, 1);
          }
        }
      }
    },
  };

  const handler = (...info) => {
    console.log("我要88平", info.join("-"));
  };
  const handler1 = (...info) => {
    console.log("我要88平1", info.join("-"));
  };
  const handler2 = (...info) => {
    console.log("我要100平", info.join("-"));
  };
  salesOffices.listen("woyao88", handler);
  salesOffices.listen("woyao88", handler1);
  salesOffices.listen("woyao100", handler2);

  salesOffices.remove("woyao88", handler1);

  salesOffices.trigger("woyao88", "100w", "88平");
  salesOffices.trigger("woyao100", "150w", "100平");
}
